package com.weilx959.spt.plugin.e2sp.controller;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.weilx959.spt.core.StageContext;
import com.weilx959.spt.core.component.VLoading;
import com.weilx959.spt.core.component.VToast;
import com.weilx959.spt.core.constants.CommonConstants;
import com.weilx959.spt.core.interfaces.Controller;
import com.weilx959.spt.core.utils.FXMLUtil;
import com.weilx959.spt.core.utils.Try;
import com.weilx959.spt.plugin.e2sp.constant.ExcelToSqlConstants;
import com.weilx959.spt.plugin.e2sp.context.ConfigurationContext;
import com.weilx959.spt.plugin.e2sp.model.Configuration;
import com.weilx959.spt.plugin.e2sp.model.ExcelVO;
import com.weilx959.spt.plugin.e2sp.service.LoadExcelService;
import com.weilx959.spt.plugin.e2sp.utils.ResourceBundleUtil;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.Tooltip;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.stage.FileChooser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * excel to sql视图控制器
 *
 * @author weilx
 * @since 2024-04-16
 */
@Slf4j
public class ExcelToSqlController implements Controller {
    @FXML
    public Label excelFileTextField;

    @FXML
    public TabPane excelDisplayTabPane;

    @FXML
    private GridPane rootPane;

    private ExcelVO excelVO;

    private final ResourceBundle bundle = ResourceBundleUtil.get();

    private final SubmitFormDialogController submitFormDialogController = FXMLUtil.getController(this.getClass(),
        ExcelToSqlConstants.SUBMIT_FORM_DIALOG, bundle);

    private final LoadExcelService loadExcelService  = new LoadExcelService();

    @Override
    public Pane getRootPane() {
        return rootPane;
    }

    /**
     * 初始化
     */
    @FXML
    private void initialize() {
        // 读取文件成功后，显示数据
        loadExcelService.setOnSucceeded(event -> {
            VLoading.end();
            excelVO = loadExcelService.getValue();
            this.displayExcel();
        });

        // 读取文件失败
        loadExcelService.setOnFailed(event -> {
            VLoading.end();
            Throwable e = loadExcelService.getException();
            String msg = bundle.getString("e2s.main.message.file-read-failed");
            log.error(msg, e);
            VToast.error(msg + e.getMessage());
        });
    }

    // 以下为插件状态事件

    /**
     * 插件展示时调用
     *
     * @param config 初始的配置
     */
    @Override
    public void onShow(Map<String, Object> config) {
        // 当视图显示时，初始化数据
        Configuration configuration = Optional.ofNullable(config)
                .map(JSON::toJSONString)
                .map(json -> JSONObject.parseObject(json, Configuration.class))
                .orElseGet(Configuration::new);
        ConfigurationContext.set(configuration);
    }

    /**
     * 程序结束时调用
     */
    @Override
    public boolean onDestroy() {
        // 当插件被卸载时，释放资源
        excelVO = null;
        submitFormDialogController.onDestroy();
        return true;
    }

    // 以下为页面事件

    /**
     * 单击打开按钮
     *
     * @param event 事件
     */
    public void openButtonClicked(MouseEvent event) {
        event.consume();
        // 打开文件选择器
        var fileChooser = new FileChooser();
        fileChooser.setTitle(bundle.getString("e2s.main.chooser.title"));
        Optional.ofNullable(excelFileTextField.getText())
            .filter(StringUtils::isNotBlank)
            .map(Paths::get)
            .map(Path::toFile)
            .map(File::getParentFile)
            .or(() -> Optional.of(Paths.get(CommonConstants.DEFAULT_APP_PATH).toFile()))
            .ifPresent(fileChooser::setInitialDirectory);
        fileChooser.getExtensionFilters()
            .add(new FileChooser.ExtensionFilter(bundle.getString("e2s.main.chooser.typename"), "*.xls", "*.xlsx"));
        var file = fileChooser.showOpenDialog(StageContext.get());

        if (Objects.isNull(file) || file.isDirectory() || !file.exists()) {
            String msg = bundle.getString("e2s.main.message.file-not-choose");
            VToast.error(msg);
            return;
        }
        VLoading.start(bundle.getString("e2s.main.message.loading-read-file"));
        // 设置文件路径
        excelFileTextField.setText(file.getAbsolutePath());
        Optional.ofNullable(excelFileTextField.getTooltip()).orElseGet(() -> {
            excelFileTextField.setTooltip(new Tooltip());
            return excelFileTextField.getTooltip();
        }).setText(file.getAbsolutePath());
        // 读取文件
        loadExcelService.filePathProperty().set(file.getAbsolutePath());
        loadExcelService.restart();
    }

    /**
     * 单击刷新按钮
     *
     * @param event 事件
     */
    public void refreshButtonClicked(MouseEvent event) {
        event.consume();
        // 刷新数据
        Try.of(() -> Optional.ofNullable(excelFileTextField.getText())
            .filter(StringUtils::isNotBlank)
            .ifPresent(file -> {
                VLoading.start(bundle.getString("e2s.main.message.loading-read-file"));
                loadExcelService.restart();
            }));
    }

    /**
     * 单击保存按钮，生成SQL语句
     *
     * @param event 事件
     */
    public void saveButtonClicked(MouseEvent event) {
        event.consume();
        if (Objects.isNull(excelVO)) {
            VToast.error(bundle.getString("e2s.main.message.file-not-choose"));
            return;
        }
        // 转换excel数据
        Try.of(() -> submitFormDialogController.onShow(excelVO)) // 显示转换后的数据
            .failure(e -> {
                String msg = bundle.getString("e2s.main.message.convert-failed");
                log.error(msg, e);
                VToast.error(msg + e.getMessage());
            });
    }

    // 以下为自定义方法

    /**
     * 显示excel
     */
    private void displayExcel() {
        excelDisplayTabPane.getTabs().clear();

        if (Objects.isNull(excelVO)) {
            VToast.error(bundle.getString("e2s.main.message.file-is-empty"));
            return;
        }
        // 显示数据
        for (ExcelVO.SheetVO sheetVO : excelVO.getSheets()) {
            // 显示sheet页
            ExcelSheetViewController sheetViewController = FXMLUtil.getController(this.getClass(), ExcelToSqlConstants.EXCEL_SHEET_VIEW);
            Tab tab = new Tab(sheetVO.getName(), sheetViewController.getRootPane());
            excelDisplayTabPane.getTabs().add(tab);
            // 显示sheet页数据
            List<ExcelVO.RowVO> rows = sheetVO.getRows();

            if (CollectionUtils.isEmpty(rows)) {
                continue;
            }
            // 取第一行为表头
            sheetViewController.setTableItems(rows.get(0), rows.subList(1, rows.size()));
        }
    }

}
